/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/cat.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../macro/head.h"
#include "../impl/head.h"
#include "../msg/head.h"
#include "../xos/head.h"

#include "jsp_parse_tag.h"
#include "jsp_cleaner.h"
#include "jsp_proc.h"
#include "helper_jsp.h"

#include "jsp_supper_variable.h"
#include "jsp_cplusplus.h"
#include "jsp_variable.h"
#include "jsp_declare.h"
#include "jsp_comment.h"
#include "jsp_html.h"
#include "jsp_cmd.h"

namespace jsp2cpp
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    helper_jsp::helper_jsp()
    {
        m_eType = JSP_HTML;
        m_pBigBuf = 0;
        m_pBuf = 0;

        m_dst_file = "";
        m_tab = "    ";
    }

    helper_jsp::~helper_jsp()
    {
        m_declare_list.put_back_to_pool();
        m_text_list.put_back_to_pool();
        m_item_list.put_back_to_pool();

        xos_stl::release_interface( m_pBigBuf );
        xos_stl::release_interface( m_pBuf );
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // proc

    // 
    // 解析jsp主方法
    // 
    int helper_jsp::proc( xos_box::i_msg *& pMsg )
    {
        int ret = 0;

        if( 0 == ret )
        {
            m_pBigBuf = mgr::container()->box()->big_buf();
            m_pBuf = mgr::container()->box()->buf();
        }

        if( 0 == ret )
        {
            const char ** argv = ( const char ** )pMsg->get_void( 0, 0 );
            int argc = pMsg->get_int( 0, 0 );
            ret = load_jsp( argc, argv );
        }

        // 扫描标签之内的东西
        while( ( 0 == ret ) && ( JSP_END != m_eType ) )
        {
            parse();
        }

        if( 0 == ret )
        {
            jsp_proc obj( this );
            obj.proc();
        }

        if( 0 == ret )
        {
            save();
        }

        // 退出前，清空一下日志
        {
            mgr::container()->log()->flush();
            mgr::get()->log_notify()->notify_type( pMsg, MSG_TYPE_FLUSH );
        }

        xos_stl::release_interface( m_pBigBuf );
        xos_stl::release_interface( m_pBuf );

        LOG4( "jsp2cpp finished. ret = %d", ret );
        mgr::get()->set_ret(ret);

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // argv[1] : src jsp file
    int helper_jsp::load_jsp( int argc, const char * argv[] )
    {
        int ret = 0;

        xos::i_file * pFile = 0;

        if( ( 0 == ret ) && ( 2 != argc - 1 ) )
        {
            LOG4( "usage : jsp2cpp.exe index.jsp index.cpp" );
            ret = 1;
        }

        if( ( 0 == ret ) && ( 0 != mgr::container()->common_misc()->end_with( argv[1], ".jsp" ) ) )
        {
            LOG4( "usage : jsp2cpp.exe index.jsp index.cpp" );
            ret = 1;
        }

        if( 0 == ret )
        {
            LOG4( "jsp2cpp cmd = %s %s %s", argv[0], argv[1], argv[2] );
        }

        if( 0 == ret )
        {
            m_dst_file = argv[2];
            pFile = mgr::container()->xos()->file();
            ret = pFile->open( argv[1], xos::i_file::XOS_FILE_READ, xos::i_file::XOS_SHARE_READ, xos::i_file::XOS_FILE_OPEN );
        }

        if( 0 == ret )
        {
            LOG4( "load jsp = %s", argv[1] );
            int len = pFile->read( m_pBigBuf );
            if( len > 0 )
            {
                m_pBigBuf->set_end_zero();
            }
            else
            {
                ret = 1;
            }
        }

        xos_stl::release_interface( pFile );

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    // 一个<>一个<>的读
    int helper_jsp::parse()
    {
        const char * lpszTag = "unknown";
        int ret = 0;

        // 保存html标签之外的字节
        if( 0 == ret )
        {
            jsp_cleaner obj( this );
            obj.proc( m_pBigBuf );
        }

        if( 0 == ret )
        {
            jsp_parse_tag obj( this );
            ret = obj.proc( m_pBigBuf, m_pBuf );
        }

        if( 0 != ret )
        {
            m_eType= JSP_END;
        }

        if( 0 == ret )
        {
            jsp_cmd obj( this );
            ret = obj.parse( m_pBigBuf, m_pBuf );
            if( 0 != ret )
            {
                lpszTag = "jsp_cmd";
            }
        }

        if( 0 == ret )
        {
            jsp_comment obj( this );
            ret = obj.parse( m_pBuf );
            if( 0 != ret )
            {
                lpszTag = "jsp_comment";
            }
        }

        if( 0 == ret )
        {
            jsp_supper_variable obj( this );
            ret = obj.parse( m_pBuf );
            if( 0 != ret )
            {
                lpszTag = "jsp_supper_variable";
            }
        }

        if( 0 == ret )
        {
            jsp_variable obj( this );
            ret = obj.parse( m_pBuf );
            if( 0 != ret )
            {
                lpszTag = "jsp_variable";
            }
        }

        if( 0 == ret )
        {
            jsp_declare obj( this );
            ret = obj.parse( m_pBuf );
            if( 0 != ret )
            {
                lpszTag = "jsp_declare";
            }
        }

        if( 0 == ret )
        {
            jsp_cplusplus obj( this );
            ret = obj.parse( m_pBuf );
            if( 0 != ret )
            {
                lpszTag = "jsp_cplusplus";
            }
        }

        if( 0 == ret )
        {
            jsp_html obj( this );
            ret = obj.parse( m_pBuf );
            if( 0 != ret )
            {
                lpszTag = "jsp_html";
            }
        }

        if( 0 != ret )
        {
            LOG4("parse jsp = %s, data len = %d", lpszTag, m_pBuf->get_len(0));
        }

        m_pBuf->set_len( 0 );
        m_pBuf->set_pos( 0 );

        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //

    int helper_jsp::push_data( data::LIST * pList, const char * lpszData, int nLen, enumJspType eType )
    {
        int ret = 0;

        data::T * pD = 0;

        if( pList->size() > 0 )
        {
            pD = pList->back();
        }

        if( pD )
        {
            int nBufSize = xos_box::i_buf::BUF_SIZE / 2;
            int len = pD->m_pBuf->get_len( 0 );
            if( nLen + len > nBufSize )
            {
                pD = 0;
            }
        }

        if( !pD || ( eType != JSP_HTML ) || ( eType != pD->m_eType ) )
        {
            pD = data::get_item_from_pool();
            pD->init();
            pD->m_eType = eType;
            pList->push_back( pD );
        }

        {
            pD->m_pBuf->add_data( lpszData, nLen, true );
        }

        return ret;
    }

    data * helper_jsp::push_item( const char * lpszData, int nLen, enumJspType eType )
    {
        data::LIST * pList = &m_item_list;
        data * pRet = 0;
        push_data( pList, lpszData, nLen, eType );
        pRet = pList->back();
        return pRet;
    }

    data * helper_jsp::push_text( const char * lpszData, int nLen, enumJspType eType )
    {
        data::LIST * pList = &m_text_list;
        data * pRet = 0;
        push_data( pList, lpszData, nLen, eType );
        pRet = pList->back();
        return pRet;
    }

    data * helper_jsp::push_declare( const char * lpszData, int nLen )
    {
        data::LIST * pList = &m_declare_list;
        data * pRet = 0;
        push_data( pList, lpszData, nLen, enumJspType::JSP_FUNCTION );
        pRet = pList->back();
        return pRet;
    }

    data::LIST * helper_jsp::declare()
    {
        return &m_declare_list;
    }

    data::LIST * helper_jsp::item()
    {
        return &m_item_list;
    }

    data::LIST * helper_jsp::text()
    {
        return &m_text_list;
    }

    const char * helper_jsp::tab()
    {
        return m_tab.c_str();
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //

    int helper_jsp::save()
    {
        int ret = 0;

        xos::i_file * pFile = 0;

        if( 0 == ret )
        {
            xos::i_dir * pDir = mgr::container()->xos()->dir();
            pDir->delete_file( m_dst_file.c_str() );
            xos_stl::release_interface( pDir );
        }

        if( 0 == ret )
        {
            pFile = mgr::container()->xos()->file();
            ret = pFile->open( m_dst_file.c_str(), xos::i_file::XOS_FILE_WRITE, 0, xos::i_file::XOS_FILE_CREATE);
        }

        for( data::ITER iter = m_text_list.begin(); ( 0 == ret ) && ( iter != m_text_list.end() ); ++iter )
        {
            data * pD = *iter;
            xos_box::i_buf * pBuf = pD->m_pBuf;
            pFile->write( pBuf );
        }

        xos_stl::release_interface( pFile );

        return ret;
    }

} // jsp2cpp
